<template>
    <div class="w-screen h-screen" ref="threeCotainer"></div>

    <div class="base-description">
        基于three.js的VR全景应用

        <div class="subtitle">-- 按住Ctrl键和鼠标右键旋转查看</div>
    </div>
</template>

<script setup lang="ts">
import { PCFSoftShadowMap, PMREMGenerator, PerspectiveCamera, Scene, WebGLRenderer } from 'three'

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

import { ref, onMounted } from 'vue'

const threeCotainer = ref<HTMLDivElement>()

const statsDom = ref<HTMLDivElement>()

onMounted(async () => {
    // 场景
    const scene = new Scene()

    // 摄像机 (视角, 宽高比, 近裁剪面, 远裁剪面)
    const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
    // 摄像机位置(坐标)
    camera.position.set(3, 0, 6)

    // 渲染器
    const renderer = new WebGLRenderer({
        // 抗锯齿
        antialias: true,
    })
    // 渲染器尺寸
    renderer.setSize(window.innerWidth, window.innerHeight)
    // 允许渲染器产生阴影
    renderer.shadowMap.enabled = true
    // 设置阴影的分辨率
    renderer.shadowMap.type = PCFSoftShadowMap

    // 设置渲染器的像素比
    renderer.setPixelRatio(window.devicePixelRatio)

    // 将渲染器的dom元素添加到页面中
    threeCotainer.value?.appendChild(renderer.domElement)

    // hdr贴图
    const hdrTexture = new RGBELoader().load('./assets/forgotten_miniland_4k.hdr', function () {
        // 使用hdr贴图生成环境贴图
        const pmremGenerator = new PMREMGenerator(renderer)
        // 生成环境贴图
        pmremGenerator.compileEquirectangularShader()
        // 设置场景背景和环境贴图
        const envMap = pmremGenerator.fromEquirectangular(hdrTexture).texture

        // 添加到场景中
        scene.background = envMap
        scene.environment = envMap

        // 释放hdr贴图
        hdrTexture.dispose()
        // 释放环境贴图
        pmremGenerator.dispose()
    })

    // 控制器
    const controls = new OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    controls.dampingFactor = 0.05
    controls.screenSpacePanning = true
    controls.minDistance = 1
    controls.maxDistance = 100
    controls.maxPolarAngle = Math.PI

    // 渲染函数
    const render = () => {
        // 更新控制器
        controls.update()
        // 渲染
        renderer.render(scene, camera)
        // 循环渲染
        requestAnimationFrame(render)
    }
    render()

    // 监听窗口变化
    window.addEventListener('resize', () => {
        // 摄像机宽高比
        camera.aspect = window.innerWidth / window.innerHeight
        // 摄像机更新投影矩阵
        camera.updateProjectionMatrix()
        // 渲染器尺寸
        renderer.setSize(window.innerWidth, window.innerHeight)
    })
})
</script>

<style lang="less" scoped></style>
